package cn.ddiancan.xddcloud.common.security;

import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

import cn.ddiancan.xddcloud.common.utils.XddcloudSreamUtils;
import org.bouncycastle.util.encoders.Hex;

public class SecurityUtil {

    // 跟秘钥组件存放服务器位置
    private static final String ROOT_KEY_COMPONENT_PATH = "/opt/security/";

    // key 文件
    private static final String KEY_COMONENT_ONE = "1.key";

    private static final String KEY_COMONENT_TOW = "2.key";

    // 根秘钥盐值
    private static final String ROOT_KEY_SALT = "m+kVLyEUcsyzUtHri8Hc/oG9gPkxsuFRzJDKXZAhBQk=";

    // 迭代次数
    private static final int ITERATION_COUNT = 10000;

    // 密钥长度
    private static final int KEY_SIZE = 256;

    // 加载根密钥
    public static byte[] rootKey = null;

    static {
        rootKey = loadRootKey();
    }

    private static byte[] loadRootKey() {
        FileInputStream fileInputStreamOne = null;
        FileInputStream fileInputStreamTow = null;
        try {
            if (rootKey == null) {
                SecurityKeyGenerator.generaterAesKey(ROOT_KEY_COMPONENT_PATH);
                fileInputStreamOne = new FileInputStream(ROOT_KEY_COMPONENT_PATH + KEY_COMONENT_ONE);
                fileInputStreamTow = new FileInputStream(ROOT_KEY_COMPONENT_PATH + KEY_COMONENT_TOW);
                String rootKeyComponentOne =
                    XddcloudSreamUtils.copyToString(fileInputStreamOne, StandardCharsets.UTF_8);
                String rootKeyComponentTwo =
                    XddcloudSreamUtils.copyToString(fileInputStreamTow, StandardCharsets.UTF_8);
                byte[] bytes = generateSeed(rootKeyComponentOne, rootKeyComponentTwo);
                SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                PBEKeySpec pbeKeySpec =
                    new PBEKeySpec(bytesToHex(bytes).toCharArray(), ROOT_KEY_SALT.getBytes(StandardCharsets.UTF_8),
                        ITERATION_COUNT, KEY_SIZE);
                secretKeyFactory.generateSecret(pbeKeySpec);
                return secretKeyFactory.generateSecret(pbeKeySpec).getEncoded();
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            XddcloudSreamUtils.close(fileInputStreamOne, fileInputStreamTow);
        }
    }

    private static byte[] generateSeed(String part1, String part2) {
        byte[] part1Bytes = Hex.decode(part1);
        byte[] part2Bytes = Hex.decode(part2);
        byte[] seed = new byte[part1Bytes.length + part2Bytes.length];
        System.arraycopy(part1Bytes, 0, seed, 0, part1Bytes.length);
        System.arraycopy(part2Bytes, 0, seed, part1Bytes.length, part2Bytes.length);
        return seed;
    }

    private static String bytesToHex(byte[] bytes) {
        return SecurityKeyGenerator.bytesToHex(bytes);
    }
}
